package com.dawn.module.hospital.service.ehealth.api;

import com.alibaba.fastjson.JSONObject;
import com.dawn.framework.common.pojo.CommonResult;
import com.dawn.framework.common.util.object.BeanUtils;
import com.dawn.module.hospital.enums.ErrorCodeConstants;
import com.dawn.module.hospital.service.ehealth.DawnHealthCardServerImpl;
import com.dawn.module.hospital.service.ehealth.bean.*;
import com.dawn.module.hospital.util.DateUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.tencent.healthcard.impl.HealthCardServerImpl;
import com.tencent.healthcard.model.CommonIn;
import com.tencent.healthcard.model.HealthCardInfo;
import com.tencent.healthcard.model.ReportHISData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author cnsu-cmh
 * @date 2024-08-24 10:54
 * @description 微信电子健康卡开放平台接口
 */
@Slf4j
public class EHealthTengmedApi {


    private static final Integer ERROR_CODE = ErrorCodeConstants.BH_ERROR.getCode();


    private static Cache<String, String> tokenCache = CacheBuilder.newBuilder().maximumSize(100)
            .expireAfterWrite(7200, TimeUnit.SECONDS).build();

    private static String getAppToken(BaseReq req) throws Exception {
        String appToken = tokenCache.getIfPresent(getTokenCacheKey(req.getHospitalId(), req.getAppId()));
        if (StringUtils.isBlank(appToken)) {
            appToken = refreshToken(req);
        }
        return appToken;
    }

    private static String refreshToken(BaseReq req) throws Exception {
        HealthCardServerImpl healthCard = new HealthCardServerImpl(req.getAppSecret());
        JSONObject appTokenObj = healthCard.getAppToken(getCommonIn("",req), req.getAppId());
        JSONObject rsp = getRsp(appTokenObj);
        String appToken = rsp.getString("appToken");
        String key = getTokenCacheKey(req.getHospitalId(), req.getAppId());
        tokenCache.put(key, appToken);
        return appToken;
    }

    private static CommonIn getCommonIn(String appToken, BaseReq req) {
        String requestId = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
        int channelNum = 0;
        CommonIn commonIn = new CommonIn(appToken,requestId,req.getHospitalId(),channelNum);
        return commonIn;
    }

    private static CommonIn getSsmCommonIn(String appToken,BaseReq req) {
        String requestId = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
        int channelNum = 4;
        CommonIn commonIn = new CommonIn(appToken,requestId,req.getHospitalId(),channelNum);
        return commonIn;
    }

    private static JSONObject getRsp(JSONObject commonRes) throws Exception {
        JSONObject commonOut = commonRes.getJSONObject("commonOut");
        if(0 == commonOut.getInteger("resultCode")) {
            JSONObject rsp = commonRes.getJSONObject("rsp");
            return rsp;
        } else {
            throw new Exception(commonOut.getString("errMsg"));
        }
    }

    private static String getTokenCacheKey(String hospId, String appId) {
        return "hospId:" + hospId + ":" + appId;
    }

    /**
     * 功能描述: 通过身份证图片获取身份证信息
     * @auther: cnsu-cmh
     * @date: 2021-01-15 16:05
     * @param ocrReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult ocrInfo(OcrReq ocrReq) {
        try {
            String appToken = getAppToken(ocrReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(ocrReq.getAppSecret());
            JSONObject ocrInfoObj = healthCard.ocrInfo(getCommonIn(appToken,ocrReq), ocrReq.getImageContent());
            JSONObject rsp = getRsp(ocrInfoObj);
            JSONObject cardInfo = rsp.getJSONObject("cardInfo");
            return CommonResult.success(cardInfo);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 注册健康卡
     * @auther: cnsu-cmh
     * @date: 2021-01-15 16:05
     * @param regReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult register(RegReq regReq) {
        try {
            String appToken = getAppToken(regReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(regReq.getAppSecret());
            HealthCardInfo healthCardInfo = BeanUtils.toBean(regReq, HealthCardInfo.class);
            JSONObject ocrInfoObj = healthCard.registerHealthCard(getCommonIn(appToken,regReq), healthCardInfo,60,60);
            JSONObject rsp = getRsp(ocrInfoObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 通过健康卡授权码获取健康卡
     * @auther: cnsu-cmh
     * @date: 2021-01-15 16:06
     * @param healthCodeReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult getByHealthCode(HealthCodeReq healthCodeReq) {
        try {
            String appToken = getAppToken(healthCodeReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(healthCodeReq.getAppSecret());
            JSONObject ocrInfoObj = healthCard.getHealthCardByHealthCode(getCommonIn(appToken,healthCodeReq), healthCodeReq.getHealthCode(),60,60);
            JSONObject rsp = getRsp(ocrInfoObj);
            JSONObject card = rsp.getJSONObject("card");
            return CommonResult.success(card);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 通过健康卡二维码获取健康卡
     * @auther: cnsu-cmh
     * @date: 2021-01-15 16:06
     * @param healthCodeReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult getByQRCode(HealthCodeReq healthCodeReq) {
        try {
            String appToken = getAppToken(healthCodeReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(healthCodeReq.getAppSecret());
            JSONObject ocrInfoObj = healthCard.getHealthCardByQRCode(getCommonIn(appToken,healthCodeReq), healthCodeReq.getQrCodeText(),60,60);
            JSONObject rsp = getRsp(ocrInfoObj);
            JSONObject card = rsp.getJSONObject("card");
            return CommonResult.success(card);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 获取健康卡二维码
     * @auther: cnsu-cmh
     * @date: 2021-01-15 18:09
     * @param qrCodeReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult getDynamicQRCode(QRCodeReq qrCodeReq) {
        try {
            String appToken = getAppToken(qrCodeReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(qrCodeReq.getAppSecret());
            JSONObject ocrInfoObj = healthCard.getDynamicQRCode(
                    getCommonIn(appToken,qrCodeReq),
                    qrCodeReq.getHealthCardId(),
                    qrCodeReq.getIdType(),
                    qrCodeReq.getIdNumber(),
                    qrCodeReq.getCodeType(),60,60);
            JSONObject rsp = getRsp(ocrInfoObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 用卡数据监测
     * @auther: cnsu-cmh
     * @date: 2021-01-18 12:33
     * @param reportDataReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult reportHISData(ReportDataReq reportDataReq) {
        try {
            String appToken = getAppToken(reportDataReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(reportDataReq.getAppSecret());
            ReportHISData reportHISData = new ReportHISData();
            reportHISData.setQrCodeText(reportDataReq.getQrCodeText());
            reportHISData.setTime(DateUtils.getDateTime());
            reportHISData.setHospitalCode(reportDataReq.getHospitalId());
            reportHISData.setScene(reportDataReq.getScene());
            reportHISData.setDepartment(reportDataReq.getDepartment());
            reportHISData.setCardChannel(reportDataReq.getCardChannel());
            reportHISData.setCardType(reportDataReq.getCardType());
            reportHISData.setCardCostTypes(reportDataReq.getCardCostTypes());
            JSONObject reportObj = healthCard.reportHISData(
                    getCommonIn(appToken,reportDataReq),
                    reportHISData,60,60);
            JSONObject rsp = getRsp(reportObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 获取卡包订单ID
     * @auther: cnsu-cmh
     * @date: 2021-01-20 11:43
     * @param orderIdReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult getOrderIdByOutAppId(HealthCodeReq orderIdReq) {
        try {
            String appToken = getAppToken(orderIdReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(orderIdReq.getAppSecret());
            JSONObject ocrInfoObj = healthCard.getOrderIdByOutAppId(getCommonIn(appToken,orderIdReq), orderIdReq.getAppId(), orderIdReq.getQrCodeText(),60,60);
            JSONObject rsp = getRsp(ocrInfoObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 绑定健康卡和院内ID关系接口
     * @auther: cnsu-cmh
     * @date: 2021-07-21 11:14
     * @param bindCardReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult bindCardRelation(BindCardReq bindCardReq) {
        try {
            String appToken = getAppToken(bindCardReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(bindCardReq.getAppSecret());
            JSONObject bindCardObj = healthCard.bindCardRelation(
                    getCommonIn(appToken,bindCardReq),
                    bindCardReq.getHospitalId(),
                    bindCardReq.getQrCodeText(),60,60);
            JSONObject rsp = getRsp(bindCardObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: 批量注册健康卡接口
     * @auther: cnsu-cmh
     * @date: 2021-07-20 14:55
     * @param regReqs:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult registerBatch(List<RegReq> regReqs) {
        RegReq regReq = regReqs.get(0);
        try {
            String appToken = getAppToken(regReq);
            HealthCardServerImpl healthCard = new HealthCardServerImpl(regReq.getAppSecret());

            List<HealthCardInfo> healthCardInfos = new ArrayList<>();
            for (RegReq req : regReqs) {
                HealthCardInfo healthCardInfo = BeanUtils.toBean(req, HealthCardInfo.class);
                healthCardInfos.add(healthCardInfo);
            }

            JSONObject batchHealthCard = healthCard.registerBatchHealthCard(getCommonIn(appToken, regReq), healthCardInfos,60,60);
            JSONObject rsp = getRsp(batchHealthCard);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    /**
     * 功能描述: openId加密
     * @auther: cnsu-cmh
     * @date: 2021-07-22 12:45
     * @param openIdReq:
     * @return: com.dawn.common.pojo.CommonResult
     */
    public static CommonResult activeCardOpenid(ActiveCardOpenidReq openIdReq) {
        try {
            String uuid = UUID.randomUUID().toString().toUpperCase().replace("-","");
            String uoh = uuid + "&" + openIdReq.getOpenId() + "&" + openIdReq.getHospitalId();
            byte[] contentBytes = uoh.getBytes();
            byte[] keyBytes = openIdReq.getAppSecret().getBytes();
            //加密
            String encrypt = encryptAESBCBase64(contentBytes,keyBytes);
            String encryptOpenId = openIdReq.getAppId() + encrypt;
            return CommonResult.success(encryptOpenId);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    private static String encryptAESBCBase64(byte[] contentBytes, byte[] keyBytes) {
        try{
            //添加一个安全管理器提供者
            Security.addProvider(new BouncyCastleProvider());
            //根据一个字节数组构造一个 SecretKey
            SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
            //设置加密类型
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
            cipher.init(Cipher.ENCRYPT_MODE, key); //用于将 Cipher 初始化为加密模式的常量。
            byte[] tmp = cipher.doFinal(contentBytes ); //操作加密或解密数据
            //返回Base64后的加密串
            return new String(Base64.encodeBase64( tmp ) );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static CommonResult ssmGenQrCode(SsmGenQrCodeReq qrCodeReq) {
        try {
            String appToken = getAppToken(qrCodeReq);
            DawnHealthCardServerImpl healthCard = new DawnHealthCardServerImpl(qrCodeReq.getAppSecret());
            JSONObject qrCodeObj = healthCard.ssmGenQrCode(
                    getSsmCommonIn(appToken,qrCodeReq),
                    qrCodeReq.getSsmId(),
                    qrCodeReq.getNotifyUrl(),60,60);
            JSONObject rsp = getRsp(qrCodeObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    public static CommonResult ssmQueryQrCodeResult(SsmQueryQrCodeReq qrCodeReq) {
        try {
            String appToken = getAppToken(qrCodeReq);
            DawnHealthCardServerImpl healthCard = new DawnHealthCardServerImpl(qrCodeReq.getAppSecret());
            JSONObject qrCodeObj = healthCard.ssmQueryQrCodeResult(
                    getSsmCommonIn(appToken,qrCodeReq),
                    qrCodeReq.getUid(),60,60);
            JSONObject rsp = getRsp(qrCodeObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    public static CommonResult getHealthCardByHealthCardId(QRCodeReq qrCodeReq) {
        try {
            String appToken = getAppToken(qrCodeReq);
            DawnHealthCardServerImpl healthCard = new DawnHealthCardServerImpl(qrCodeReq.getAppSecret());
            JSONObject qrCodeObj = healthCard.getHealthCardByHealthCardId(
                    getSsmCommonIn(appToken,qrCodeReq),
                    qrCodeReq.getHealthCardId(),60,60);
            JSONObject rsp = getRsp(qrCodeObj);
            JSONObject card = rsp.getJSONObject("card");
            return CommonResult.success(card);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    public static CommonResult machineGenQrCode(SsmGenQrCodeReq qrCodeReq) {
        try {
            String appToken = getAppToken(qrCodeReq);
            DawnHealthCardServerImpl healthCard = new DawnHealthCardServerImpl(qrCodeReq.getAppSecret());
            JSONObject qrCodeObj = healthCard.machineGenQrCode(
                    getSsmCommonIn(appToken,qrCodeReq),
                    qrCodeReq.getSsmId(),
                    qrCodeReq.getNotifyUrl(),60,60);
            JSONObject rsp = getRsp(qrCodeObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    public static CommonResult machineQueryQrCodeResult(SsmQueryQrCodeReq qrCodeReq) {
        try {
            String appToken = getAppToken(qrCodeReq);
            DawnHealthCardServerImpl healthCard = new DawnHealthCardServerImpl(qrCodeReq.getAppSecret());
            JSONObject qrCodeObj = healthCard.machineQueryQrCodeResult(
                    getSsmCommonIn(appToken,qrCodeReq),
                    qrCodeReq.getUid(),60,60);
            JSONObject rsp = getRsp(qrCodeObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    public static CommonResult registerUniformVerifyOrder(RegisterUniformVerifyOrderReq verifyOrderReq) {

        try {
            String appToken = getAppToken(verifyOrderReq);
            DawnHealthCardServerImpl healthCard = new DawnHealthCardServerImpl(verifyOrderReq.getAppSecret());
            JSONObject qrCodeObj = healthCard.registerUniformVerifyOrder(
                    getCommonIn(appToken,verifyOrderReq),
                    verifyOrderReq.getCardType(),verifyOrderReq.getIdCard(),verifyOrderReq.getName(),60,60);
            JSONObject rsp = getRsp(qrCodeObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }

    public static CommonResult checkUniformVerifyResult(CheckUniformVerifyReq checkUniformVerifyReq) {

        try {
            String appToken = getAppToken(checkUniformVerifyReq);
            DawnHealthCardServerImpl healthCard = new DawnHealthCardServerImpl(checkUniformVerifyReq.getAppSecret());
            JSONObject qrCodeObj = healthCard.checkUniformVerifyResult(
                    getCommonIn(appToken,checkUniformVerifyReq),
                    checkUniformVerifyReq.getVerifyOrderId(),checkUniformVerifyReq.getRegisterOrderId(),60,60);
            JSONObject rsp = getRsp(qrCodeObj);
            return CommonResult.success(rsp);
        } catch (Exception e) {
            return CommonResult.error(ERROR_CODE, e.getMessage());
        }
    }
}
